package org.KeyCrafter.cmd;

import org.KeyCrafter.key.GenericKey;
import org.KeyCrafter.key.StringKey;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * sflag 在书 140 页
 */
public class CommandBuilder {
    /**
     * 便于后续进行数组到字典的转化，减少时间复杂度
     */
    public static final int KeyCrafter_CMD_WRITE = 1;
    public static final int KeyCrafter_CMD_READONLY = 2;
    public static final int KeyCrafter_CMD_DENYOOM = 4;
    public static final int KeyCrafter_CMD_SORT_FOR_SCRIPT = 256;

    private final static String PROC_PREFIX = "CMD_PROC_";

    // 命令表
    public final static List<Command> commandTable = new ArrayList<>();

    // 构建命令
    static {
        buildCmdSet(DBCommand.class);
        buildCmdSet(StringCommand.class);
        buildCmdSet(HashCommand.class);
        buildCmdSet(ListCommand.class);
        buildCmdSet(SetCommand.class);
        buildCmdSet(ZSetCommand.class);
        buildCmdSet(ServerCommand.class);
        populateCommandTable();
    }

    static void populateCommandTable() {
        // 根据字符串 FLAG 生成实际 FLAG
        for (Command c : commandTable) {
            char[] arr = c.sflags.toCharArray();
            for (char f : arr) {
                switch (f) {
                    case 'w':
                        c.flags |= KeyCrafter_CMD_WRITE;
                        break;
                    case 'r':
                        c.flags |= KeyCrafter_CMD_READONLY;
                        break;
                    case 'm':
                        c.flags |= KeyCrafter_CMD_DENYOOM;
                        break;
                    case 'S':
                        c.flags |= KeyCrafter_CMD_SORT_FOR_SCRIPT;
                        break;
                    default:
                        break;
                }
            }

        }

    }

    // 从命令集合（CmdSet）中查找命令信息（CmdInfo）并创建命令
    private static void buildCmdSet(Class<?> cmdSet) {
        // 判断是不是一个命令集合
        CmdSet cmdSetAnno = cmdSet.getAnnotation(CmdSet.class);
        if (cmdSetAnno == null) {
            return;
        }
        Method[] methods = cmdSet.getDeclaredMethods();
        for (Method method : methods) {
            CmdInfo cmdInfo = method.getAnnotation(CmdInfo.class);
            if (cmdInfo != null) {
                Command cmd = buildCmd(cmdInfo);
                if (cmd != null) {
                    commandTable.add(cmd);
                }
            }
        }
    }

    //  根据注解生成一条命令
    public static Command buildCmd(CmdInfo cmdInfo) {
        String name = cmdInfo.name();
        int arity = cmdInfo.arity();
        String sflags = cmdInfo.sflags();
        int firstKey = cmdInfo.firstKey();
        int lastKey = cmdInfo.lastKey();
        int keyStep = cmdInfo.keyStep();
        //  查找处理函数
        CommandProc proc;
        try {
            // 匹配函数
            Field field = CmdProcRefs.class.getField(PROC_PREFIX + name.toUpperCase());
            proc = (CommandProc)field.get(null);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
            return null;
        }
        return new Command(name,proc,arity,sflags,firstKey,lastKey,keyStep);
    }

    private CommandBuilder() {
    }
}
